package com.ruoyi.algorithm.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.algorithm.config.UploadImage;
import com.ruoyi.algorithm.entity.Image;
import com.ruoyi.algorithm.entity.ImageVersion;
import com.ruoyi.algorithm.entity.Manufacturer;
import com.ruoyi.algorithm.entity.OperatorVersion;
import com.ruoyi.algorithm.model.ImageModel;
import com.ruoyi.algorithm.model.ListImageRequestModel;
import com.ruoyi.algorithm.repository.ImageRepository;
import com.ruoyi.algorithm.repository.ImageVersionRepository;
import com.ruoyi.algorithm.repository.ManufacturerRepository;
import com.ruoyi.algorithm.repository.OperatorVersionRepository;
import com.ruoyi.algorithm.service.ImageService;
import com.ruoyi.algorithm.util.MybatisUtils;
import com.ruoyi.algorithm.util.VersionUtil;
import com.ruoyi.algorithm.util.harbor.HttpUtils;
import com.beihu.sightplus.common.authorization.service.UserAuthorization;
import com.beihu.sightplus.common.response.PageResult;
import com.beihu.sightplus.common.string.MyStringUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.logging.Logger;
import java.util.stream.Collectors;

/**
 * @author dyk
 * @date 2021/7/8 16:44
 * @description
 */
@Service
public class ImageServiceImpl implements ImageService {

    Logger logger = Logger.getLogger(ImageServiceImpl.class.getName());

    @Value("${docker.tar.path:D://imageUpload/}")
    private String tarPath; //tar包临时存放路径

    @Value("${docker.host}")
    private String DOCKER_HOST;//加载的IP

    @Value("${docker.harbor.username}")
    private String HARBOR_USERNAME;//harbor用户名

    @Value("${docker.harbor.password}")
    private String HARBOR_PASSWORD;//harbor密码

    @Value("${docker.harbor.ip}")
    private String HARBOR_LOGIN_IP;//harbor的IP

    @Value("${docker.harbor.address}")
    private String HARBOR_ADDRESS;//harbor地址

    @Resource
    private ImageRepository imageRepository;

    @Resource
    private ImageVersionRepository imageVersionRepository;

    @Resource
    private ManufacturerRepository manufacturerRepository;

    @Resource
    private OperatorVersionRepository operatorVersionRepository;

    /**
     * 添加镜像
     *
     * @param image
     * @return
     */
    @Override
    public boolean addImage(Image image) {
        image.setCreateTime(new Date());
        image.setDelFlag("0");
        image.setCreateUser(UserAuthorization.getUserAuthorization().getId());
        return imageRepository.save(image);
    }

    /**
     * 上传镜像到镜像仓库
     *
     * @param multipartFile
     * @param imageId
     * @return
     */
    @Override
    public ImageVersion UploadImage(MultipartFile multipartFile, Long imageId) {
        String version;
        long size = multipartFile.getSize();

        Image image = imageRepository.getById(imageId);

        String softwareName = image.getImageName();
        // 获取镜像对应的厂商
        Manufacturer manufacturer = manufacturerRepository.getById(image.getManufacturerId());

        String projectName = MyStringUtil.getChineseToPinyin(manufacturer.getName()) + manufacturer.getId().toString();

        // 建立harbor项目路径
        JSONObject map = new JSONObject();
        map.put("count_limit", "0");
        map.put("project_name", projectName);
        JSONObject metadata = new JSONObject();
        metadata.put("public", "true");
        map.put("metadata", metadata);
        HttpUtils.sendPost(HARBOR_ADDRESS + "/api/v2.0/projects", map, HARBOR_USERNAME, HARBOR_PASSWORD);

        // 初始化路径
        File file = new File(tarPath);
        if (!file.exists()) {
            file.mkdir();
        }
        try {

            String lastVersion = image.getLastVersion();
            version = VersionUtil.upgradeVersion(lastVersion);
            logger.info("版本号为：" + version);
            image.setLastVersion(version);
            String imageName = HARBOR_LOGIN_IP + "/" + projectName + "/" + MyStringUtil.getChineseToPinyin(softwareName) + ":" + version;
            boolean result = new UploadImage(HARBOR_LOGIN_IP, DOCKER_HOST, HARBOR_USERNAME, HARBOR_PASSWORD, imageName, multipartFile.getInputStream(),
                    tarPath + UUID.randomUUID() + multipartFile.getOriginalFilename())
                    .uploadResp();

            if (!result) {
                logger.info("上传失败！！");
                return null;
            } else {
                // 修改版本号
                image.setUpdateTime(new Date());
                imageRepository.saveOrUpdate(image);

                //版本信息存入数据库
                ImageVersion imageVersion = new ImageVersion();
                imageVersion.setCreateUser(UserAuthorization.getUserAuthorization().getId());
                imageVersion.setImageId(imageId);
                imageVersion.setDelFlag("0");
                imageVersion.setCreateTime(new Date());
                imageVersion.setFileSize(size);
                imageVersion.setTag(version);
                imageVersion.setImagePath(imageName);
                imageVersionRepository.save(imageVersion);
                return imageVersionRepository.getById(imageVersion.getId());
            }
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        } finally {

        }
    }

    @Override
    public boolean updateImage(Image image) {
        image.setUpdateTime(new Date());
        return imageRepository.saveOrUpdate(image);
    }

    /**
     * 详情
     *
     * @param id
     * @return
     */
    @Override
    public Image detail(Long id) {
        return imageRepository.getById(id);
    }

    /**
     * 删除镜像
     *
     * @param id
     * @return
     */
    @Override
    @Transactional
    public boolean deleteImage(Long id) {

        // 查询镜像下有没有版本未删除
        int count = imageVersionRepository.count(new LambdaQueryWrapper<ImageVersion>()
                .eq(ImageVersion::getDelFlag, "0")
                .eq(ImageVersion::getImageId, id));
        if (count > 0) {
            logger.info("有镜像版本，无法删除！");
            return false;
        }

        Image image = new Image();
        image.setId(id);
        image.setDelFlag("1");
        image.setUpdateTime(new Date());
        boolean result = imageRepository.updateById(image);
        return result;
    }

    /**
     * 删除镜像版本
     *
     * @param id
     * @return
     */
    @Override
    public boolean deleteImageVersion(Long id) {
        // 判断是否有算子版本依赖
        int count = operatorVersionRepository.count(new LambdaQueryWrapper<OperatorVersion>()
                .eq(OperatorVersion::getImageVersionId, id)
                .eq(OperatorVersion::getDelFlag, "0"));
        if (count > 0) {
            return false;
        }

        boolean result = false;
        ImageVersion imageVersion = new ImageVersion();
        imageVersion.setId(id);
        imageVersion.setDelFlag("1");
        result = imageVersionRepository.saveOrUpdate(imageVersion);
        return result;
    }

    /**
     * 分页查询镜像版本
     *
     * @param imageId
     * @return
     */
    @Override
    public List<ImageVersion> listImageVersion(Long imageId) {
        List<ImageVersion> list = imageVersionRepository.list(new LambdaQueryWrapper<ImageVersion>()
                .eq(ImageVersion::getImageId, imageId)
                .eq(ImageVersion::getDelFlag, "0"));

        return list;
    }

    /**
     * 查询删除的镜像版本
     *
     * @param imageId
     * @return
     */
    @Override
    public List<ImageVersion> listHistoryImageVersion(Long imageId) {
        List<ImageVersion> list = imageVersionRepository.list(new LambdaQueryWrapper<ImageVersion>()
                .eq(ImageVersion::getImageId, imageId)
                .eq(ImageVersion::getDelFlag, "1"));
        return list;
    }

    /**
     * 恢复历史历史版本
     *
     * @param id
     * @return
     */
    @Override
    public boolean recoverImageVersion(Long id) {

        ImageVersion imageVersion = new ImageVersion();
        imageVersion.setId(id);
        imageVersion.setUpdateTime(new Date());
        imageVersion.setDelFlag("0");

        return imageVersionRepository.saveOrUpdate(imageVersion);
    }

    /**
     * 分页查询镜像
     *
     * @param model
     * @return
     */
    @Override
    public PageResult listImage(ListImageRequestModel model) {
        PageResult pageResult = new PageResult();
        String jsonString = JSON.toJSONString(model);
        Image image = JSONObject.parseObject(jsonString, Image.class);
        QueryWrapper<Image> queryWrapper = Wrappers.query(image)
                .eq("del_flag", "0");
        // 构建排序条件
        MybatisUtils.getOrderBy(queryWrapper, model);

        // 分页条件
        Page<Image> imagePage = new Page<>();
        imagePage.setSize(model.getSize());
        imagePage.setCurrent(model.getCurrent());

        // 分页查询
        Page<Image> resultPage = imageRepository.page(imagePage, queryWrapper);
        pageResult.setContent(resultPage.getRecords());
        pageResult.setTotalPages(resultPage.getPages());
        pageResult.setTotalSize(resultPage.getTotal());

        return pageResult;
    }


    /**
     * 检查版本号是否重复
     *
     * @param version
     * @return true存在重复，false不重复
     */
    private boolean checkVersion(String version, Long imageId) {
        int count = imageVersionRepository.count(new LambdaQueryWrapper<ImageVersion>()
                .eq(ImageVersion::getImageId, imageId)
                .eq(ImageVersion::getTag, version));
        if (count > 0) {
            return true;
        }
        return false;
    }
    /**
     * 获取镜像名与版本列表（下拉框）
     *
     * @return 镜像携带版本实体
     */
    @Override
    public List<ImageModel> findImageDropDownBox() {
        ArrayList<ImageModel> imageModels = new ArrayList<>();
        List<Image> images = imageRepository.list(Wrappers.lambdaQuery(Image.class)
                .select(Image::getImageName,Image::getId)
                .eq(Image::getDelFlag, "0"));
        for (Image image : images) {
            Long imageId = image.getId();
            String imageName = image.getImageName();
            List<ImageVersion> imageVersions = imageVersionRepository.list(Wrappers.lambdaQuery(ImageVersion.class)
                    .select(ImageVersion::getTag)
                    .eq(ImageVersion::getImageId,imageId)
                    .eq(ImageVersion::getDelFlag, "0"));
            imageModels.add(new ImageModel(imageName, imageVersions.stream().map(ImageVersion::getTag).collect(Collectors.toList())));
        }
        return imageModels;
    }

}
